﻿using System;
using System.Collections.Generic;
using GameFramework.Battle.Core;
using Gameplay.PVE.Utils;
using RootMotion.FinalIK;
using UnityEngine;
using UnityEngine.AI;
using Yoozoo.Managers;

namespace Gameplay.PVE.Survivor
{
    public class BehaviorComponent: ComponentBase
    {
        private BehaviorTree behaviorTree;
        private bool enableBehavior = true;
        private bool isPause = false;
        private EEnemyAIType aiType;

        public void InitAI(EEnemyAIType aiType)
        {
            this.aiType = aiType;
            if (aiType == EEnemyAIType.SearchAllMap)
            {
                unit.behaviorState = EBehaviorState.Battle;
            }
            else
            {
                unit.behaviorState = EBehaviorState.Idle;
            }
        }
        
        protected override void OnInitialized()
        {
            isPause = StageManager.Instance.IsPause;
            enableBehavior = true;//unit.team == 0;
            behaviorTree = ClassManager.Get<BehaviorTree>();
            behaviorTree.Initialize(BattleConfigManager.Instance.GetBehaviorData(2));
            behaviorTree.SetVariable(ESharedVariablesType.Executor, unit);
            if (unit.team == 0)
            {
                unit.behaviorState = EBehaviorState.Battle;
            }
            else
            {
                unit.behaviorState = EBehaviorState.Idle;
            }
        }

        protected override void OnUpdate()
        {
            if (unit.isDead)
            {
                return;
            }

            if (isPause)
            {
                return;
            }
            if (!enableBehavior)
            {
                return;
            }

            if (unit.locked)
            {
                return;
            }

            if (unit.behaviorState == EBehaviorState.Idle)
            {
                UpdateIdleState();
                return;
            }
            if (interactPoint != BattleConstValue.DEFAULT_POINT)
            {
                UpdateInteractPoint();
            }
            else if (isMoving)
            {
                UpdateMoving();
            }
            else
            {
                behaviorTree?.Update();
            }
        }

        protected override void OnDead()
        {
            base.OnDead();
            enableBehavior = false;
        }

        private void UpdateMoving()
        {
            Vector3 targetPosition = Vector3.zero;
            if (moveType == 0)
            {
                targetPosition = unit.summonOffset;
            }
            else if (moveType == 1)
            {
                targetPosition = Vector3.zero;
            }
            var position = offset;
            var diff = targetPosition - position;
            var frameSpeed = unit.moveSpeed * Time.deltaTime;
            if (diff.sqrMagnitude <= frameSpeed * frameSpeed)
            {
                offset = targetPosition;
                if (moveType == 0)
                {
                    isMoving = false;
                }
            }
            else
            {
                offset = position + diff.normalized * frameSpeed;
            }
            unit.Position = StageManager.Instance.TeamGroup.Position + offset;
        }
        
        private bool isMoving;
        private int moveType;
        private Vector3 offset;

        public void StartMove(int moveType)
        {
            this.moveType = moveType;
            isMoving = true;
            offset = unit.Position - StageManager.Instance.TeamGroup.Position;
        }

        public void EndMove()
        {
            moveType = 0;
        }
        
        private Vector3 interactPoint = BattleConstValue.DEFAULT_POINT;
        private bool hasReach = false;
        private bool originAgentActive;
        
        public void StartInteractByMission(Vector3 point)
        {
            interactPoint = point;
            hasReach = false;
            originAgentActive = unit.IsNavmeshAgentActive();
            unit.SetNavmeshAgentActive(true);
        }

        private NavMeshPath path;
        private int nextPathIndex = 0;
        private List<Vector3> pathList = new List<Vector3>();
        private Vector3 interactableForward;
        
        public void MoveToInteractable(Vector3 point,Vector3 forward)
        {
            interactPoint = point;
            hasReach = false;
            //originAgentActive = unit.IsNavmeshAgentActive();
            unit.SetNavmeshAgentActive(false);
            if (path == null)
            {
                path = new NavMeshPath();
            }
            pathList.Clear();
            if (NavMesh.CalculatePath(unit.position, point, NavMesh.AllAreas, path))
            {
                for (int i = 0; i < path.corners.Length; i++)
                {
                    pathList.Add(path.corners[i]);
                }
            }
            else
            {
                pathList.Add(unit.position);
                pathList.Add(point);
            }
            
            interactableForward = forward;
            nextPathIndex = 1;
        }

        public void StopInteractByMission()
        {
            if (interactPoint == BattleConstValue.DEFAULT_POINT)
            {
                return;
            }
            interactPoint = BattleConstValue.DEFAULT_POINT;
            unit.Play("Idle");
            if (unit.cachedTargetPosition != BattleConstValue.DEFAULT_POINT)
            {
                unit.TargetPosition = unit.cachedTargetPosition;
            }
            else
            {
                unit.TargetPosition = unit.Position;
                unit.TargetForward = interactableForward;
            }
            unit.SetAgentTargetPosition(unit.TargetPosition);
            unit.cachedTargetPosition = BattleConstValue.DEFAULT_POINT;
            unit.SetNavmeshAgentActive(unit.team != 0);
        }
        
        private void UpdateInteractPoint()
        {
            /*unit.TargetPosition = interactPoint;
            unit.SetAgentTargetPosition(unit.TargetPosition);*/
            if (hasReach)
            {
                unit.TargetForward = interactableForward;
                return;
            }
            //UnityEngine.Debug.LogError(Vector3.Distance(unit.Position, interactPoint) + " " + unit.Position + " " + interactPoint);
            /*if (Vector3.Distance(unit.Position, interactPoint) <= 0.1f)
            {
                unit.SetSpeed(0);
                //unit.Play("Interact");
                hasReach = true;
            }*/
            var currentPosition = unit.position;
            if (pathList.Count > nextPathIndex)
            {
                var nextPoint = pathList[nextPathIndex];
                var diff = nextPoint - currentPosition;
                var speedThisFrame = unit.moveSpeed * Time.deltaTime;
                if (diff.sqrMagnitude <= speedThisFrame * speedThisFrame)
                {
                    nextPathIndex++;
                    unit.Position = nextPoint;
                    if (nextPathIndex >= pathList.Count)
                    {
                        hasReach = true;
                        unit.SetSpeed(0);
                        unit.TargetForward = interactableForward;
                        return;
                    }
                }
                else
                {
                    currentPosition += diff.normalized * speedThisFrame;
                    unit.Position = currentPosition;
                    unit.SetSpeed(1);
                }
                unit.TargetForward = diff;
            }
        }

        private void UpdateIdleState()
        {
            if (aiType == EEnemyAIType.SearchTarget)
            {
                unit.SearchTarget();
            }
            else if (aiType == EEnemyAIType.SearchBattlePoint)
            {
                unit.SearchBattlePoint();
            }
        }

        public void OnPause()
        {
            isPause = true;
        }

        public void OnResume()
        {
            isPause = false;
        }
        
        public override void OnReset()
        {
            base.OnReset();
            ClassManager.Free(behaviorTree);
            behaviorTree = null;
            enableBehavior = false;
            interactPoint = BattleConstValue.DEFAULT_POINT;
            hasReach = false;
            originAgentActive = false;
            isMoving = false;
        }
    }
}
